﻿using System;
using System.Collections.Generic;
using System.Web;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;

using JigsawService.Parsers;
using JigsawService.Utility;

namespace JigsawService.DataAccess.Usage
{
    /// <summary>
    /// Event data is not replicated.
    /// 
    /// Each type of event has its own XML structure.
    /// A public method accepts parameters that fits the specific event structure
    /// (which enforces the structure and validates the data),
    /// and in turn calls the generic SaveEvent method to store the data.
    /// </summary>
    public class EventLogDA : JigsawBase
    {
        APIMessage _apimessage;
        string _dbstr;

        public EventLogDA(APIMessage apiMessage)
        {
            _apimessage = apiMessage;
            // read the database connection string from the web.config file
            _dbstr = ConfigurationManager.AppSettings["UsageDB"].ToString();
        }

        /// <summary>
        /// Stores UI click events to determine which parts of a given application are used most heavily
        /// </summary>
        /// <param name="formName"></param>
        public void ClickStream(string appName, string appEventName)
        {
            _apimessage.StateMessage = "EventLogDA ClickStream: ";
            string eventXML = "<ClickStream><AppName>" + appName + "</AppName><AppEventName>" + appEventName + "</AppEventName></ClickStream>";
            SaveEvent("Client", "ClickStream", eventXML);
        }

        /// <summary>
        /// Writing to the event log does not need to be transactional, but it is done to be 
        /// consistent with the standard for all action queries in the Jigsaw framework.
        /// No unique constraint or referential integrity tests are required.
        /// </summary>
        /// <param name="errSource"></param>
        /// <param name="errorDetail"></param>
        /// <param name="apiMessage"></param>
        /// <returns></returns>
        private void SaveEvent(string eventsource, string eventname, string eventmessage)
        {
            _apimessage.StateMessage = "EventLogDA SaveEvent: ";
            using (SqlConnection sqlConn = new SqlConnection(_dbstr))
            {
                sqlConn.Open();
                SqlTransaction sqlTran = sqlConn.BeginTransaction();
                SqlCommand sqlCmd = new SqlCommand();
                sqlCmd.Connection = sqlConn;
                sqlCmd.Transaction = sqlTran;

                // define parameterized dml
                string dmlCmd = "Insert Into EventLog" +
                                " (UserID, SessionID, Location, SourceType, EventName, EventMessage)" +
                                " Values (@UserID, @SessionID, @Location, @SourceType, @EventName, @EventMessage)";

                // assign input parameters as values to the dml parameters
                sqlCmd.Parameters.Add("@UserID", SqlDbType.VarChar, 50).Value = _apimessage.UserID;
                sqlCmd.Parameters.Add("@SessionID", SqlDbType.VarChar, 50).Value = _apimessage.SessionGUID;
                sqlCmd.Parameters.Add("@Location", SqlDbType.VarChar, 50).Value = _apimessage.Location;
                sqlCmd.Parameters.Add("@SourceType", SqlDbType.VarChar, 10).Value = eventsource;
                sqlCmd.Parameters.Add("@EventName", SqlDbType.VarChar, 50).Value = eventname;
                sqlCmd.Parameters.Add("@EventMessage", SqlDbType.VarChar, -1).Value = eventmessage;

                try
                {
                    // assign the dml to the sql command object, and execute the transaction
                    sqlCmd.CommandText = dmlCmd;
                    sqlCmd.ExecuteNonQuery();
                    sqlTran.Commit();
                    SetSuccessResult("New EventLog record saved.", "text", _apimessage);
                }
                catch (Exception ex)
                {
                    // rollback transaction and close connection
                    if (sqlConn.State == ConnectionState.Open)
                    {
                        sqlTran.Rollback();
                        sqlConn.Close();
                    }
                    // rethrow error, to be handled at the service level
                    throw;
                }
            }
        }


    }
}